﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevComponents.DotNetBar;
using System.Net;
using System.Threading;
using System.Net.Sockets;
using System.Xml;
using StuMana.Services;
using System.IO;

namespace StuMana.UI
{
    public partial class CheckInOut : Office2007Form
    {
        List<Devices> liDevices = new List<Devices>();
        
        public CheckInOut()
        {
            InitializeComponent();
            CheckInOut_initial();
        }
        
        string ProPath;
        byte[] serial_buff = new byte[40];
        Services.SL025M rfid_reader = new Services.SL025M();
        Services.COM connect;
        private Bitmap image;
        private System.Windows.Forms.Timer readTimer;
        private string tag = "";
        private Boolean isSelect = false;
        private Services.student print_std = new Services.student();
        // get size of return byteArray
        private int size;

        public string Gate = "";

        public delegate void AsyncCallback(IAsyncResult ar);
        public delegate void AddTolstDiscoveredDevices(object o);

        private UdpState GlobalUDP;

        /// <summary>
        ///  UDP
        /// </summary>
        struct UdpState
        {
            public System.Net.IPEndPoint EP;
            public System.Net.Sockets.UdpClient UDPClient;      
            
        }
        
     public  class DefPacket
        {
            public byte[] _data;
            public string _ip;

            public DefPacket()
            {
           
            }
            public DefPacket( byte[] data, string ip)
            {
                _data = data;
                _ip = ip;
            }
            
        }


     /// Danh sách các gói tin
        List<DefPacket> liPacketUDP = new List<DefPacket>();
        /// <summary>
        /// Thread Receive 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void ReceivePacket()
        {
            if (btnStart.Text == "Stop")
            {
                while (true)
                {
                    IPEndPoint ep;
                    try
                    {                       
                        ep = new IPEndPoint(0, 30303);
                        byte[] receiveData = GlobalUDP.UDPClient.Receive(ref ep);
                        if (receiveData.Length > 0)
                        {
                            DefPacket p = new DefPacket(receiveData, ep.Address.ToString());
                            liPacketUDP.Add(p);
                        }
                    }
                    catch (Exception e)
                    {
						// if (GlobalUDP.UDPClient.Available > 0)
                           //     GlobalUDP.UDPClient.Close();
                    }
                    Thread.Sleep(30);
                }
            }
        }

        /// <summary>
        /// Thread Process
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Process()
        {
            while (true)
            {
                if (liPacketUDP.Count() > 0)
                {
                    try
                    {
                        DefPacket p = liPacketUDP.ElementAt(0); 
                        byte[] recData = p._data;   
                        string ip = p._ip;

                        Devices dev = new Devices();
                        dev._ipState = p._ip;
                        dev._ipDymate = p._ip;

                        dev.GetHostName(liDevices);
                        Gate = dev._gateName;

                        string ReceiveString = Encoding.ASCII.GetString(recData);
                        liPacketUDP.RemoveAt(0);
                  
                        ReceiveString = ReceiveString.Replace("\r\n", "\n");
                        //MessageBox.Show(ReceiveString.ToString() + Gate.ToString() + "Process");
                
                        serial_buff = FromHex(ReceiveString);
                        tag = get_student_tagID().ToString();

                        gPanelMiddle.Invoke(new AddTolstDiscoveredDevices(show_stdInfo), tag);
                    }
                    catch (Exception ex)
                    {
                      //  MessageBox.Show(ex.ToString(), "Warning 4 4");
                    }
                }
                Thread.Sleep(50);
            }
        }

        Thread thReceive;
        Thread thProcess;
        private void cmdDiscoverDevices_Click(object sender, EventArgs e)
        {
            try
            {
                // Try to send the discovery request message
                byte[] DiscoverMsg = Encoding.ASCII.GetBytes("Discovery: Who is out there?");
                
                GlobalUDP.UDPClient.Send(DiscoverMsg, DiscoverMsg.Length, new System.Net.IPEndPoint(System.Net.IPAddress.Parse("255.255.255.255"), 30303));
            }
            catch
            {
                MessageBox.Show("Unable to transmit discovery message.  Check network connectivity and ensure that no other instances of this program are running.", "Error", MessageBoxButtons.OK);
                return;
            }
        }

        public void ReceiveCallback(IAsyncResult ar)
        {
            UdpState MyUDP = (UdpState)ar.AsyncState;
            // Obtain the UDP message body and convert it to a string, with remote IP address attached as well
            if (btnStart.Text == "Stop")
            {
                try
                {
                    Byte[] receiBytes = MyUDP.UDPClient.EndReceive(ar, ref MyUDP.EP);
                   
                    string ReceiveString = Encoding.ASCII.GetString(receiBytes);

                    DefPacket p = new DefPacket(receiBytes, MyUDP.EP.Address.ToString());
                    liPacketUDP.Add(p);

                    //MessageBox.Show(ReceiveString.ToString() + "1");

                    ReceiveString = ReceiveString.Replace("\r\n", "\n");

                    // Configure the UdpClient class to accept more messages, if they arrive
                    MyUDP.UDPClient.BeginReceive(ReceiveCallback, MyUDP);
                }
                catch (Exception e)
                {
                //    MessageBox.Show(e.Message, "Warning 12");
                }
            }
        }

        public static byte[] FromHex(string hex)
        {
            hex = hex.Replace("-", "");
            byte[] raw = new byte[hex.Length / 2];
            for (int i = 0; i < raw.Length; i++)
            {
                raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
            }
            return raw;
        }
        /*--------------------------------------------------------------*/

        // user initial 
        private void CheckInOut_initial()
        {
            // get project directory
            ProPath = Environment.CurrentDirectory;

            //pictureBox 
            ProPath += "\\images\\logo.jpg";
            image = new Bitmap(Image.FromFile(ProPath), new Size(refImage.Width, refImage.Height));
            refImage.Image = image;

            //timer setting
            readTimer = new System.Windows.Forms.Timer();
            readTimer.Interval = 200;
            readTimer.Tick += new EventHandler(readTimer_Tick);

            labelItemStatus.Text = "Gate Control OFF";
        }

        // timer event handler
        private void readTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                rfid_reader.selectCard();
                size = connect.getdata(serial_buff);
                // login
                if (serial_buff[3] != 0x01 && size != 5000 && isSelect == false)
                {
                  //  ts_label.Text = "Checking";
                    labelItemStatus.Text = "Checking";
                    readTimer.Enabled = false;

                    // login to tag
                    rfid_reader.LogIn();
                    size = connect.getdata(serial_buff);

                    // ReadData from tag
                    if (serial_buff[3] == 0x02 && size != 5000)
                        rfid_reader.ReadData();
                    else
                    {
                        readTimer.Enabled = true;
                        throw new Exception("Login fail");
                    }
                    size = connect.getdata(serial_buff);

                    //Receive data
                    if (serial_buff[3] == 0x00 && size != 5000)
                    {
                        tag = get_student_tagID().ToString();
                        show_stdInfo(tag);
                        isSelect = true;
                    }
                    else
                    {
                        readTimer.Enabled = true;
                        throw new Exception("Data isn't received");
                    }

                    readTimer.Enabled = true;
                }
                else if (serial_buff[3] == 0x01)
                {
                    isSelect = false;
                }
                else if (size == 5000)
                {
                    //    ts_label.Text = "No Signal";
                    labelItemStatus.Text = "No Signal ";
                }
            }
            catch (Exception es)
            {
                string msg = es.Message;               
            }
        }

        // change tagID into 
        private Int32 get_student_tagID()
        {

            Byte[] temp_byte = { 0x00, 0x00, 0x00, 0x00 };
            temp_byte[2] = serial_buff[6];
            temp_byte[1] = serial_buff[5];
            temp_byte[0] = serial_buff[4];
            Int32 temstr = BitConverter.ToInt32(temp_byte, 0);
            return temstr;
        }

        public void show_stdInfo(object o)
        {
            string tagID = (string)(o);
            try
            {
                if (print_std.getStdInfo(tagID))
                {                  
                    // change stt inout in database
                    print_std.change_stt(tagID);
                    print_std.Gate = Gate; // gate student check 

                     int hour = 12;  // 12:00:00 
                     int hourNow = DateTime.Now.Hour;
                     if (hourNow > 12)
                     {
                        // MessageBox.Show("10");
                         // > 12 => chieu
                         if (print_std.Time2 == "")
                         {
                             print_std.index = 0;
                         }
                         else
                         {
                             //xet co phai lan dau tien = 1 
                             // con lai = 0 
                             if (student.CheckTime(print_std.TagID, 2))
                             {
                                 print_std.index = 0;
                             }
                             else
                                 print_std.index = 2;
                         }
                     }
                     else
                     {                       
                         // < 12 => sang 
                         if (print_std.LateTime == "")
                         {
                            // MessageBox.Show("1");
                             print_std.index = 0;
                         }
                         else
                         {
                             // xet co phai lan dau tien =1 
                             // con lai 0
                         //    MessageBox.Show(student.CheckTime(print_std.TagID, 1).ToString());
                             if (student.CheckTime(print_std.TagID, 1))
                             {
                                 print_std.index = 0;
                           //      MessageBox.Show("2");
                             }
                             else
                             {
                                 print_std.index = 1;
                           //      MessageBox.Show("3");
                             }
                         }   
                     }
                    //Insert to database the information of check in-out
                    print_std.AddNewActivity();

                    lblGateName.Text = Gate.ToString();

                    //show info to FORM
                    lblTagID.Text = print_std.TagID.ToString();
                    lblFullName.Text = print_std.Name;
                    lblClass.Text = print_std.Class;
                    lblGender.Text = print_std.Gender;

                    if (print_std.Class == Gate)
                    {
                        lblMessage.Visible = false;
                        lblStatus.Visible = true;
                        if (!print_std.InOut)
                            lblStatus.Text = "IN";
                        else
                            lblStatus.Text = "OUT";
                    }
                    else
                    {
                        lblStatus.Visible = false;
                        lblMessage.Visible = true;
                        lblMessage.Text = print_std.Name + " is not belong class" + lblGateName.Text.ToString();
                    }

                    try
                    {
                        ProPath = Environment.CurrentDirectory;
                        ProPath += "\\images\\" + lblTagID.Text + ".jpg";
                        image = new Bitmap(Image.FromFile(ProPath), new Size(refImage.Width, refImage.Height));
                        refImage.Image = image;
                    }
                    catch(Exception  ex)
                    {
                        string msg = ex.Message;
                        ProPath = Environment.CurrentDirectory;
                        ProPath += "\\images\\logo.jpg";
                        image = new Bitmap(Image.FromFile(ProPath), new Size(refImage.Width, refImage.Height));
                        refImage.Image = image;
                    }
                }
                else
                    resetForm();
            }
            catch (Exception ex)
            {
                string msg = ex.Message;                
                ProPath = Environment.CurrentDirectory;
                ProPath += "\\images\\logo.jpg";
                image = new Bitmap(Image.FromFile(ProPath), new Size(refImage.Width, refImage.Height));
                refImage.Image = image;
            }
        }

        // form reset
        private void resetForm()
        {
            lblTagID.Text = "None";
            lblFullName.Text = "None";
            lblClass.Text = "None";
            lblGender.Text = "None";
            lblStatus.Text = "NONE";
            lblMessage.Visible = false;
            ProPath = Environment.CurrentDirectory;
            ProPath += "\\images\\logo.jpg";
            image = new Bitmap(Image.FromFile(ProPath), new Size(refImage.Width, refImage.Height));
            refImage.Image = image;
        }
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (btnStart.Text == "Start")
            {
                try
                {
                    GlobalUDP.UDPClient = new UdpClient();
                    GlobalUDP.EP = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("255.255.255.255"), 30303);
                    System.Net.IPEndPoint BindEP = new System.Net.IPEndPoint(System.Net.IPAddress.Any, 30303);

                    // Set the local UDP port to listen on
                    GlobalUDP.UDPClient.Client.Bind(BindEP);

                    // Enable the transmission of broadcast packets without having them be received by ourself
                    GlobalUDP.UDPClient.EnableBroadcast = true;
                    GlobalUDP.UDPClient.MulticastLoopback = false;

                    // Configure ourself to receive discovery responses

                    GlobalUDP.UDPClient.BeginReceive(ReceiveCallback, GlobalUDP);
                    //// broadcast discovery 
                    thReceive = new Thread(new ThreadStart(ReceivePacket));
                    thProcess = new Thread(new ThreadStart(Process));

                    //thread nhận tin bắt đầu 
                    thReceive.Start();
                    //  thread process bắt đầu
                    thProcess.Start();
                    // Transmit the discovery request message

                    labelItemStatus.Text = "Wifi listenning";
                    btnStart.Text = "Stop";
                }
                catch
                {
                    MessageBox.Show("Unable to transmit discovery message.  Check network connectivity and ensure that no other instances of this program are running.", "Error", MessageBoxButtons.OK);
                    return;
                }
            }
            else
            {

                GlobalUDP.UDPClient.Close();
                // dừng thread nhận 
                // dừng thread xử lý            
             //  thReceive.Suspend();
                //     thProcess.Suspend();
                thReceive.Abort();
                thProcess.Abort();
                readTimer.Enabled = false;
                readTimer.Dispose();
                btnStart.Text = "Start";
                labelItemStatus.Text = "None";            
            }
        }
      
        // Initial COM connecting
        public void InitialConnect(StuMana.Services.COM conn)
        {
            connect = conn;
            rfid_reader.conn = conn.serialPort;
        }

        public static string ByteArrayToString(byte[] ba)
        {
            StringBuilder hex = new StringBuilder(ba.Length * 2);
            foreach (byte b in ba)
                hex.AppendFormat("{0:x2}", b);
            return hex.ToString();
        }

        private bool flag = false;
        private bool co = false;
        private Font fontForAll = null;
        private StyleManager managerStyle = new DevComponents.DotNetBar.StyleManager();

        public void ReadSetting()
        {
            XmlReader reader = XmlReader.Create("Settings.xml");
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element
                && reader.Name == "font")
                {
                    string name = reader.GetAttribute(0).ToString();
                    string style = reader.GetAttribute(1).ToString();
                    float size = float.Parse(reader.GetAttribute(2).ToString());

                    if (style == "Bold")
                        fontForAll = new System.Drawing.Font(reader.GetAttribute(0).ToString(), size, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                    if (style == "Italic")
                        fontForAll = new System.Drawing.Font(reader.GetAttribute(0).ToString(), size, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                    if (style == "Regular")
                        fontForAll = new System.Drawing.Font(reader.GetAttribute(0).ToString(), size, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                    if (style == "Strikeout")
                        fontForAll = new System.Drawing.Font(reader.GetAttribute(0).ToString(), size, System.Drawing.FontStyle.Strikeout, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                    if (style == "Underline")
                        fontForAll = new System.Drawing.Font(reader.GetAttribute(0).ToString(), size, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0)));

                    while (reader.NodeType != XmlNodeType.EndElement)
                    {
                        reader.Read();
                        if (reader.Name == "managerstyle" && reader.NodeType == XmlNodeType.Element)
                        {
                            reader.Read();
                            string stylemana = reader.Value.ToString();
                            if (stylemana == "Office2007Blue")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2007Blue;
                            if (stylemana == "Office2007Silver")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2007Silver;
                            if (stylemana == "Office2007Black")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2007Black;
                            if (stylemana == "Windows7Blue")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Windows7Blue;
                            if (stylemana == "Office2007VistaGlass")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2007VistaGlass;
                            if (stylemana == "Office2010Silver")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2010Silver;
                            if (stylemana == "Office2010Blue")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2010Blue;
                            if (stylemana == "Office2010Black")
                                managerStyle.ManagerStyle = DevComponents.DotNetBar.eStyle.Office2010Black;
                        }
                    }
                }
            }
            reader.Close();
        }

        public void ConfigSetting()
        {
            ReadSetting();
            for (int i = 0; i < Controls[0].Controls[1].Controls[3].Controls.Count; i++)
            {
                if (Controls[0].Controls[1].Controls[3].Controls[i] is LabelX)
                {
                    Controls[0].Controls[1].Controls[3].Controls[i].Font = fontForAll;
                }
            }
            styleManager1 = managerStyle;
        }
      
       
        private void CheckInOut1_Load(object sender, EventArgs e)
        {
            liDevices.Add(new Devices("192.168.0.106","169.254.1.1","10A1"));
            liDevices.Add(new Devices("192.168.0.107", "169.254.245.35", "10A2"));
            lblMessage.Visible = false;
            flag = true;
            ConfigSetting();
            co = true;
        }
 
        private void CheckInOut1_FormClosed(object sender, FormClosedEventArgs e)
        {
            Environment.Exit(Environment.ExitCode);
            Application.ExitThread();
            Application.Exit();
        }

        private void CheckInOut1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Environment.Exit(Environment.ExitCode);
            Application.ExitThread();
            Application.Exit();
        }

        private void btnStart_Resize(object sender, EventArgs e)
        {
          
        }

        private void CheckInOut1_Resize(object sender, EventArgs e)
        {

            if (this.Focus())
            {
                int wPanel = this.gPanelStatus.Size.Width;
                int hPanel = this.gPanelStatus.Size.Height;

                int w2Panel = ((int)(wPanel / 2));
                int h2Panel = ((int)(hPanel / 2));

                int wPanel2 = this.lblStatus.Size.Width;
                int hPanel2 = this.lblStatus.Size.Height;

                int w2Panel2 = ((int)(wPanel2 / 2));
                int h2Panel2 = ((int)(hPanel2 / 2));

                int x = w2Panel - w2Panel2;
                int y = h2Panel - h2Panel2;


                this.lblStatus.Location = new Point(x, y);
                this.refImage.Size = new System.Drawing.Size(this.gPanelPicture.Size.Width - 5, this.gPanelPicture.Size.Height - 5);
                //Image img = refImage.Image;
                //refImage.Image = img;


                if (lblTagID.Text != "None")
                {
                    ProPath = Environment.CurrentDirectory;
                    ProPath += "\\images\\" + lblTagID.Text + ".jpg";


                    if (File.Exists(ProPath))
                    {
                        image = new Bitmap(Image.FromFile(ProPath), new Size(refImage.Width, refImage.Height));
                        refImage.Image = image;
                    }
                    else
                    {
                        ProPath = Environment.CurrentDirectory;
                        ProPath += "\\images\\logo.jpg";
                        image = new Bitmap(Image.FromFile(ProPath), new Size(refImage.Width, refImage.Height));
                        refImage.Image = image;
                    }
                }
                else
                {
                    ProPath = Environment.CurrentDirectory;
                    ProPath += "\\images\\logo.jpg";
                    image = new Bitmap(Image.FromFile(ProPath), new Size(refImage.Width, refImage.Height));
                    refImage.Image = image;
                }
                

               
            }
       }
    }
}
